package com.zdsoft.site.thread;

import java.util.PriorityQueue;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 1）wait()、notify()和notifyAll()方法是本地方法，并且为final方法，无法被重写。
　　 2）调用某个对象的wait()方法能让当前线程阻塞，并且当前线程必须拥有此对象的monitor（即锁）
　　 3）调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程，如果有多个线程都在等待这个对象的monitor，则只能唤醒其中一个线程；
　　 4）调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程；
 */
public class TestProducer {
	private Logger logger=LoggerFactory.getLogger(getClass());
	private int queueSize = 10;
	private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);

	@Test
	public void test() throws InterruptedException{
		TestProducer test = new TestProducer();
	    Producer producer = test.new Producer();
	    Consumer consumer = test.new Consumer();
	      
	    producer.start();
	    consumer.start();
	    Thread.sleep(50000);
	}
	
	class Consumer extends Thread {

		@Override
		public void run() {
			consume();
		}

		private void consume() {
			while (true) {
				synchronized (queue) {
					while (queue.size() == 0) {
						try {
							logger.debug("队列空，等待数据");
							queue.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
							queue.notify();
						}
					}
					queue.poll(); // 每次移走队首元素
					queue.notify();
					logger.debug("从队列取走一个元素，队列剩余{}个元素",queue.size());
				}
			}
		}
	}

	class Producer extends Thread {

		@Override
		public void run() {
			produce();
		}

		private void produce() {
			while (true) {
				synchronized (queue) {
					while (queue.size() == queueSize) {
						try {
							logger.debug("队列满，等待有空余空间");
							queue.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
							queue.notify();
						}
					}
					queue.offer(1); // 每次插入一个元素
					queue.notify();
					logger.debug("向队列取中插入一个元素，队列剩余空间：{}",(queueSize - queue.size()));
				}
			}
		}
	}
}
